#数据准备

from sklearn.datasets import fetch_lfw_people
data_home = 'D:\\机器基础\\ml-lesson\\03_dataset\\item7'

faces = fetch_lfw_people(min_faces_per_person=60, data_home=data_home) #仅选取至少60张照片的数据
x, y = faces.data, faces.target
target_names = faces.target_names     #姓名
n_samples, h, w = faces.images.shape   #返回样本数量和图片尺寸（特征变量）
print(target_names)  	#显示名人的姓名
print(n_samples,h,w)	#显示样本数量与照片尺寸

#数据降维处理

from sklearn.decomposition import  PCA   #

n_components = 150 #目标维度
pca = PCA(n_components=n_components, svd_solver='randomized', whiten=True, random_state=70).fit(x)
eigenfaces = pca.components_.reshape((n_components, h, w)) #提取特征值
x_pca = pca.transform(x) #将训练集转化为低维度的特征变量

#以三行五列的形式展示降维处理后的照片
import matplotlib.pyplot as plt
fig, ax = plt.subplots(3, 5)
for i, axi in enumerate(ax.flat):
    axi.imshow(eigenfaces[i].reshape(h, w), cmap='bone')
    axi.set(xticks=[], yticks=[])
plt.show()

#训练及评估模型

from sklearn.svm import SVC   #支持向量机的分类器
from sklearn.model_selection import GridSearchCV  #网格搜索法
from sklearn.metrics import classification_report   #分类器的评估报告
from sklearn.model_selection import train_test_split

#拆分原始数据集
x_train, x_test, y_train, y_test = train_test_split(x_pca, y, test_size=400, random_state=42)
param_grid={'C':[1,5,10,50,100],'gamma':[0.0001,0.0005,0.001,0.005,0.01,0.1]}
grid=GridSearchCV(SVC(kernel="rbf",random_state=0),param_grid=param_grid,cv=5)  #使用网格搜索法寻找最优参数值
grid.fit(x_train, y_train)
print("最优参数值为:{grid.best_params_}")
model = grid.best_estimator_  #获取最优模型
pred = model.predict(x_test)
re = classification_report(y_test, pred, target_names=target_names)
print(re)

#显示分类结果

fig, ax = plt.subplots(4, 6)
for i, axi in enumerate(ax.flat):
    axi.imshow(eigenfaces[i].reshape(h, w),cmap='bone')  #绘制图像
    axi.set(xticks=[], yticks=[])
    box = dict(fc='red', alpha=0.5)     #预先设置预测结果的边框效果
    axi.set_ylabel(target_names[pred[i]].split()[-1], bbox=None if pred[i] == y_test[i] else box)   #设置预测姓名， 以及预测结果的边框样式
plt.rcParams['font.sans-serif'] = 'Simhei'
plt.suptitle('预测名人姓名(红色边框表示预测错误)', size=10)
plt.show()